package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.form.ScPriceconfOcForm;
import cn.huiyunche.base.service.interfaces.ScPriceconfOcService;
import cn.huiyunche.base.service.mappers.ScPriceconfOcMapper;
import cn.huiyunche.base.service.mappers.ext.ScPriceconfOcExtMapper;
import cn.huiyunche.base.service.model.ScPriceconfOc;
import cn.huiyunche.base.service.model.ScPriceconfOcExample;
import cn.huiyunche.base.service.query.ScPriceconfOcQueryConditions;
import cn.huiyunche.base.service.vo.PageVo;
import cn.huiyunche.base.service.vo.ScPriceconfOcVo;
import cn.huiyunche.tools.basic.exceptions.BusinessException;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @FileName: cn.huiyunche.base.service.interfaces.impl
 * @Description: Description
 * @author: Aaron
 * @date: 2017/3/13 下午4:59
 */
@Service
public class ScPriceconfOcServiceImpl implements ScPriceconfOcService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScPriceconfOcServiceImpl.class);

    @Autowired
    private ScPriceconfOcMapper scPriceconfOcMapper;

    @Autowired
    private ScPriceconfOcExtMapper scPriceconfOcExtMapper;

    @Override
    public Integer add(ScPriceconfOcForm form, BindingResult br) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.add param : {}", form);

        if (form == null) {
            LOGGER.error("ScPriceconfOcServiceImpl.add param form must not be null");
            throw new IllegalArgumentException("表单不能为空");
        }

        //表单验证
        verificationForm(br);

        //业务验证
        verificationBusiness(form);

        //查询当前生效的记录，更新失效时间未添加记录的生效时间
        ScPriceconfOc currentOc = this.selectByEffectiveDateAndVehicleTypeId(form.getVehicleTypeId(), new Date());
        if (null != currentOc) {
            currentOc.setInvalidDate(form.getEffectiveDate());
            this.updateSelective(currentOc);
        }

        ScPriceconfOc mile = new ScPriceconfOc();
        BeanUtils.copyProperties(form, mile);

        return scPriceconfOcMapper.insertSelective(mile);
    }

    private void verificationBusiness(ScPriceconfOcForm form) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.verificationBusiness param : {}", form);

        List<ScPriceconfOc> list = this.selectByVehicleTypeId(form.getVehicleTypeId());
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        /**
         * 是否已经存在未激活的油耗变动
         * 激活时间大于
         */
        List<ScPriceconfOc> collect = list.stream().filter(
                o -> -1 != o.getEffectiveDate().compareTo( new DateTime().withMillisOfDay(0).toDate() )
        ).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(collect)) {

            if ( null != form.getId() ){
                if ( CollectionUtils.isNotEmpty(collect.stream().filter( o -> o.getId() == form.getId() ).collect(Collectors.toList())) ) {
                    return ;
                }
            }

            if ( 1 < collect.size()) {
                LOGGER.error("ScPriceconfOcServiceImpl.verificationBusiness already exist not active record");
                throw new BusinessException("车型油耗已经存在未生效的记录");
            }

            ScPriceconfOc oc = collect.get(0);
            if (null != form.getId() && form.getId() == oc.getId()) {
                return ;
            }
            if ( form.getEffectiveDate().compareTo(oc.getEffectiveDate()) == 1 ){
                return ;
            }

            LOGGER.error("ScPriceconfOcServiceImpl.verificationBusiness already exist not active record");
            throw new BusinessException("车型油耗已经存在未生效的记录");
        }
    }

    private void verificationForm(BindingResult br) {

        if (null == br) {
            LOGGER.error("ScPriceconfOcServiceImpl.verificationForm error br is null");
            throw new IllegalArgumentException("BindingResult is null");
        }

        if (br.hasErrors()) {
            List<ObjectError> list = br.getAllErrors();
            LOGGER.error("ScPriceconfOcServiceImpl.verificationForm error : {}", list.get(0).getDefaultMessage());
            throw new IllegalArgumentException(list.get(0).getDefaultMessage());
        }
    }

    @Override
    public void update(ScPriceconfOcForm form, BindingResult br) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.update param : {}", form);

        if (form == null) {
            LOGGER.error("ScPriceconfOcServiceImpl.update param form must not be null");
            throw new IllegalArgumentException("表单不能为空");
        }

        //表单验证
        verificationForm(br);

        //业务验证
        verificationBusiness(form);

        //查询当前生效的记录，更新失效时间未添加记录的生效时间
        ScPriceconfOc currentMile = this.selectByEffectiveDateAndVehicleTypeId(form.getVehicleTypeId(), new Date());
        if (null != currentMile) {
            currentMile.setInvalidDate(form.getEffectiveDate());
            this.updateSelective(currentMile);
        }

        ScPriceconfOc mile = new ScPriceconfOc();
        BeanUtils.copyProperties(form, mile);

        this.updateSelective(mile);
    }

    @Override
    public void updateSelective(ScPriceconfOc oc) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.updateSelective param : {}", oc);

        if (null == oc) {
            LOGGER.error("ScPriceconfOcServiceImpl.updateSelective param oc must not be null");
            throw new IllegalArgumentException("线路价格变动不能为空");
        }

        scPriceconfOcMapper.updateByPrimaryKeySelective(oc);
    }

    @Override
    public void del(Integer id) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.del param : {}", id);

        if ( null ==  id || 0 == id.intValue() ) {
            LOGGER.error("ScPriceconfOcServiceImpl.del param id must not be null");
            throw new IllegalArgumentException("主键不能为空");
        }

        ScPriceconfOc priceconfOc = selectByPrimaryKey(id);
        if ( null == priceconfOc ){
            LOGGER.error("ScPriceconfOcServiceImpl.del mile is null");
            throw new BusinessException("记录不存在");
        }

        Date today = new DateTime().withMillisOfDay(0).toDate();
        if ( 1 != priceconfOc.getEffectiveDate().compareTo(today)  ) {
            LOGGER.error("ScPriceconfOcServiceImpl.del mile can not delete");
            throw new BusinessException("只能删除未生效的记录");
        }

        scPriceconfOcMapper.deleteByPrimaryKey(id);

        //更新当前记录失效时间为空
        ScPriceconfOc currentOc = this.selectByEffectiveDateAndVehicleTypeId(priceconfOc.getVehicleTypeId(), new Date());
        if ( null != currentOc ) {
            currentOc.setInvalidDate(null);
            scPriceconfOcMapper.updateByPrimaryKey(currentOc);
        }
    }

    @Override
    public ScPriceconfOc selectByEffectiveDateAndVehicleTypeId(Integer vehicleTypeId, Date effectiveDate) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.selectByEffectiveDate params : {}, {}", vehicleTypeId, effectiveDate);

        if (vehicleTypeId == null || 0 == vehicleTypeId.intValue()) {
            LOGGER.error("ScPriceconfOcServiceImpl.selectByEffectiveDate param vehicleTypeId must not be null");
            throw new IllegalArgumentException("车型分类主键不能为空");
        }
        if (effectiveDate == null) {
            LOGGER.error("ScPriceconfOcServiceImpl.selectByEffectiveDate param effectiveDate must not be null");
            throw new IllegalArgumentException("生效时间不能为空");
        }

        ScPriceconfOcExample example = new ScPriceconfOcExample();
        example.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId)
                .andEffectiveDateLessThanOrEqualTo(effectiveDate)
                .andInvalidDateIsNull();

        List<ScPriceconfOc> list = scPriceconfOcMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(list)) {
            ScPriceconfOcExample example1 = new ScPriceconfOcExample();
            example1.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId)
                    .andEffectiveDateLessThanOrEqualTo(effectiveDate)
                    .andInvalidDateGreaterThan(effectiveDate);

            list = scPriceconfOcMapper.selectByExample(example1);
        }

        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }

        return null;
    }

    @Override
    public List<ScPriceconfOc> selectByVehicleTypeId(Integer vehicleTypeId) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.selectByvehicleTypeId param : {}", vehicleTypeId);

        if (null == vehicleTypeId || 0 == vehicleTypeId.intValue()) {
            LOGGER.error("ScPriceconfOcServiceImpl.selectByvehicleTypeId param vehicleTypeId must not be null");
            throw new BusinessException("线路主键不能为空");
        }

        ScPriceconfOcExample example = new ScPriceconfOcExample();
        example.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId);

        return scPriceconfOcMapper.selectByExample(example);
    }

    @Override
    public Map<String, Object> selectListByConditions(PageVo pageVo, ScPriceconfOcQueryConditions conditions) throws Exception {
        if (null == conditions) {
            LOGGER.error("ScPriceconfOcServiceImpl.selectListByConditions param conditions must not be null");
        }

        Map<String, Object> map = new HashMap<>();

        String orderByClause = null;
        if (null != pageVo) {
            orderByClause = StringUtils.isNotBlank(pageVo.getOrder()) == true ? pageVo.getOrder() : " po.gmt_create DESC";
        }

        Map<String, Object> paramsMap = new HashedMap();

        if (null != conditions.getVehicleTypeId()) {
            paramsMap.put("vehicle_type_id", conditions.getVehicleTypeId());
        }

        if (StringUtils.isNotBlank(conditions.getVehicleClassifyName())) {
            paramsMap.put("vehicle_classify_name", "%" + conditions.getVehicleClassifyName() + "%");
        }

        if (null != conditions.getFuelTypeId()) {
            paramsMap.put("fuel_type_id", conditions.getFuelTypeId());
        }

        if (null != conditions.getFuelConsumption()) {
            paramsMap.put("current_value", conditions.getFuelConsumption());
        }

        if (null != conditions.getEffectiveDate()) {
            paramsMap.put("effective_date", conditions.getEffectiveDate());
        }

        if (null != conditions.getInvalidDate()) {
            paramsMap.put("invalid_date", conditions.getInvalidDate());
        }

        if (null != pageVo) {
            pageVo.setTotalRecord(scPriceconfOcExtMapper.countByConditions(paramsMap));
            paramsMap.put("limitStart", pageVo.getStartIndex());
            paramsMap.put("limitEnd", pageVo.getPageSize());
            paramsMap.put("orderByClause", orderByClause);
        }

        List<ScPriceconfOcVo> list = scPriceconfOcExtMapper.selectByConditions(paramsMap);

        //更新标示
        if ( CollectionUtils.isNotEmpty(list) ) {
            Date today = new DateTime().withMillisOfDay(0).toDate();
            list.stream().forEach( o -> {
                if ( 1 != o.getEffectiveDate().compareTo(today) ) {
                    o.setIsLock(true);
                }
            } );
        }
        map.put("list", list);

        if (null != pageVo) {
            map.put("page", pageVo);
        }

        return map;
    }

    @Override
    public ScPriceconfOc selectByPrimaryKey(Integer id) throws Exception {
        LOGGER.info("ScPriceconfOcServiceImpl.selectByPrimaryKey param : {}", id);

        if (null == id || 0 == id.intValue()) {
            LOGGER.error("ScPriceconfOcServiceImpl.selectByPrimaryKey param id must not be null");
            throw new IllegalArgumentException("主键不能为空");
        }

        return scPriceconfOcMapper.selectByPrimaryKey(id);
    }

    @Override
    public ScPriceconfOc selectEffective(Integer vehicleTypeId, Date effectiveDate) {
        LOGGER.info("ScPriceconfOcServiceImpl.selectEffective param : {}", vehicleTypeId);

        if (null == vehicleTypeId || 0 == vehicleTypeId.intValue()) {
            LOGGER.error("ScPriceconfOcServiceImpl.selectEffective param vehicleClassifyId must not be null");
            throw new IllegalArgumentException("车型分类主键不能为空");
        }
        if ( null == effectiveDate ) {
            LOGGER.error("ScPriceconfOcServiceImpl.selectEffective param effectiveDate must not be null");
            throw new IllegalArgumentException("生效时间不能为空");
        }

        ScPriceconfOcExample example = new ScPriceconfOcExample();
        example.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId)
            .andEffectiveDateLessThanOrEqualTo(effectiveDate)
            .andInvalidDateIsNull();

        List<ScPriceconfOc> list = scPriceconfOcMapper.selectByExample(example);

        if ( CollectionUtils.isEmpty(list) ){

            ScPriceconfOcExample example1 = new ScPriceconfOcExample();
            example1.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId)
                    .andEffectiveDateLessThanOrEqualTo(effectiveDate)
                    .andInvalidDateGreaterThan(effectiveDate);

            list = scPriceconfOcMapper.selectByExample(example1);
        }

        return CollectionUtils.isNotEmpty(list) == true ? list.get(0) : null;
    }
}
